Skip to content

feat: SDK update for version 0.29.0#102

Open
ArnabChatterjee20k wants to merge 7 commits intomainfrom
dev
Open

feat: SDK update for version 0.29.0#102
ArnabChatterjee20k wants to merge 7 commits intomainfrom
dev

Conversation

@ArnabChatterjee20k
Copy link
Copy Markdown
Member

@ArnabChatterjee20k ArnabChatterjee20k commented Apr 20, 2026

This PR contains updates to the SDK for version 0.29.0.

What's Changed

  • Breaking: Added subscribe message flow for Realtime subscription updates.
  • Breaking: Added close() support for Realtime subscriptions.
  • Added: Added subscriptions metadata to Realtime events for targeted callbacks.
  • Updated: Updated X-Appwrite-Response-Format header to 1.9.2.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This PR bumps the SDK to v0.29.0, introducing a new standalone Realtime class in src/services/realtime.ts with per-subscription ID tracking, update()/close() support, and lifecycle callbacks. All service files rename the Platform import to RNPlatform for clarity, and X-Appwrite-Response-Format is updated to 1.9.2.

  • Silent event drop regression (src/services/realtime.ts): handleResponseEvent returns early when subscriptions is absent or empty, removing the channel-based fallback that existed in client.ts. Any server event without subscription metadata (older server versions, public channels, race with subscribe response) will fire zero callbacks.
  • window.localStorage access without guard (src/services/realtime.ts): accessed directly on every connected message, throwing a TypeError in React Native and producing console errors; client.ts already guards this with typeof window !== 'undefined' && window.localStorage.

Confidence Score: 3/5

Not safe to merge — the new Realtime class silently drops all events when the server omits subscription metadata, which is a direct regression in the primary realtime event delivery path

The P1 finding in handleResponseEvent breaks the core use case: any subscription that receives an event without the subscriptions field will never fire its callback. This is the entire point of the SDK's realtime feature. The window.localStorage issue is P2 (caught by try/catch) but adds noisy errors in the React Native environment this SDK targets.

src/services/realtime.ts — specifically handleResponseEvent (silent drop) and handleResponseConnected (localStorage guard)

Important Files Changed

Filename Overview
src/services/realtime.ts New high-level Realtime class with per-subscription IDs; drops the channel-based event fallback, causing silent event loss when the server omits subscriptions metadata, and accesses window.localStorage without a guard
src/client.ts Rewrites realtime internals with slot-to-subscriptionId mapping; exports JSONbig; previously flagged issues (window.localStorage guard, subscribe/response race, shiftedSlot heuristic) remain unaddressed
src/services/tables-db.ts Renames Platform to RNPlatform import (consistent with other services); still contains unused expo-file-system and react-native imports
src/index.ts Exports the new Realtime class and RealtimeSubscription type; no issues found
src/models.ts Adds RowList and Row model types for the TablesDB service; straightforward addition
package.json Bumps version to 0.29.0 and adds @xmldom/xmldom and uuid overrides
CHANGELOG.md Adds 0.29.0 entry documenting subscribe flow, close() support, subscriptions metadata, and response format header bump to 1.9.2

Reviews (6): Last reviewed commit: "chore: update React Native SDK to 0.29.0" | Re-trigger Greptile

Comment thread CHANGELOG.md
Comment thread README.md Outdated
Comment thread src/client.ts
Comment thread src/client.ts
Comment thread src/client.ts Outdated
@ArnabChatterjee20k ArnabChatterjee20k changed the title feat: React Native SDK update for version 0.28.0 feat: React Native SDK update for version 0.29.0 Apr 23, 2026
Comment thread src/client.ts
Comment on lines +535 to +553
case 'connected': {
const messageData = <RealtimeResponseConnected>message.data;

let session = this.config.session;
if (!session) {
const cookie = JSONbig.parse(window.localStorage.getItem('cookieFallback') ?? '{}');
session = cookie?.[`a_session_${this.config.project}`];
}
if (session && !messageData?.user) {
this.realtime.socket?.send(JSONbig.stringify(<RealtimeRequest>{
type: 'authentication',
data: {
session
}
}));
}

this.realtime.sendSubscribeMessage();
break;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Subscribe message sent before authentication confirmation

sendSubscribeMessage() is called immediately after the authentication message is dispatched, with no acknowledgement that the server has authenticated the client. If the server processes subscribe requests before completing the authentication handshake, subscriptions to user-scoped channels will be evaluated without the user's permission context and may silently fall back to guest-level access.

Comment thread src/services/account.ts
import type { UploadProgress, Payload } from '../client';
import * as FileSystem from 'expo-file-system';
import { Platform } from 'react-native';
import { Platform as RNPlatform } from 'react-native';
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aliased cause name conflict was coming as we are importing realtime.ts from web

Comment thread src/services/realtime.ts
const timestamp = data.timestamp as string;
const subscriptions = data.subscriptions as string[] | undefined;

if (!channels || !events || !payload || !subscriptions || subscriptions.length === 0) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Silent event drop when subscriptions field is absent

handleResponseEvent returns early if subscriptions is undefined or empty, so any event the server sends without subscription-ID metadata is silently discarded — no callback ever fires. The previous implementation in client.ts fell back to channel-name matching in that case (data.channels.some(channel => subscription.channels.includes(channel))). Removing the fallback is a regression: servers that don't yet populate subscriptions in event payloads (or public-channel events sent before a subscribe response arrives) will produce zero callbacks.

Consider keeping the channel-based fallback path when subscriptions is absent or empty:

if (!channels || !events || !payload) {
    return;
}

if (subscriptions && subscriptions.length > 0) {
    for (const subscriptionId of subscriptions) {
        const subscription = this.activeSubscriptions.get(subscriptionId);
        if (!subscription) continue;
        subscription.callback({ events, channels, timestamp, payload, subscriptions });
    }
} else {
    // fallback: match by channel name
    for (const subscription of this.activeSubscriptions.values()) {
        if (channels.some(ch => subscription.channels.has(ch))) {
            subscription.callback({ events, channels, timestamp, payload, subscriptions: [] });
        }
    }
}

@ArnabChatterjee20k ArnabChatterjee20k changed the title feat: React Native SDK update for version 0.29.0 feat: SDK update for version 0.29.0 Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants